package labox.innovation.util;

import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import labox.innovation.config.Config;
import labox.innovation.gameserver.Announcements;
import labox.innovation.gameserver.Shutdown;

/**
 * 
 * �������߳�
 * 
 */
public class DeadLockDetector extends Thread {

	private static Logger _log = LoggerFactory.getLogger(DeadLockDetector.class.getName());

	private static final int _sleepTime = Config.DEADLOCK_CHECK_INTERVAL * 1000;

	private final ThreadMXBean tmx;

	public DeadLockDetector() {
		super("DeadLockDetector");
		tmx = ManagementFactory.getThreadMXBean();// ���� Java �������߳�ϵͳ�Ĺ��� Bean
		setDaemon(true);
		start();
	}

	@Override
	public final void run() {
		_log.info("DeadLockDetector started successfully",Config.SERVER_ID,"����������");
		boolean deadlock = false;
		while (!deadlock) {
			try {
				// ����ϴ�Ĳ���
				long[] ids = tmx.findDeadlockedThreads();// ������Ϊ�ȴ��ö�����������ӵ��ͬ������������״̬���߳�ѭ�������ÿ���߳�ӵ��һ������ͼ����һ������ѭ���е��̻߳�ȡ����е���ʱ���̻߳���ѭ���д�������
															// ״̬���ȴ���������

				if (ids != null) {
					deadlock = true;
					ThreadInfo[] tis = tmx.getThreadInfo(ids, true, true);// ����ÿ���̵߳��߳���Ϣ���߳�
																			// ID
																			// λ����������
																			// ids
																			// �У����ж�ջ���ٺ�ͬ����Ϣ
					String info = "DeadLock Found!\n";
					for (ThreadInfo ti : tis) {
						info += ti.toString();
					}

					for (ThreadInfo ti : tis) {
						LockInfo[] locks = ti.getLockedSynchronizers();// ����
																		// LockInfo
																		// �������飬ÿ������Ԫ�ر�ʾ������
																		// ThreadInfo
																		// ���̵߳�ǰ��Ŀ�ӵ��ͬ������
						MonitorInfo[] monitors = ti.getLockedMonitors();// ����
																		// MonitorInfo
																		// �������飬ÿ������Ԫ�ر�ʾ������
																		// ThreadInfo
																		// ���̵߳�ǰ��Ķ��������
						if (locks.length == 0 && monitors.length == 0) {
							continue;
						}

						ThreadInfo dl = ti;
						info += "Java-level deadlock:\n";
						info += "\t" + dl.getThreadName() + " is waiting to lock " + dl.getLockInfo().toString() + " which is held by " + dl.getLockOwnerName() + "\n";
						while ((dl = tmx.getThreadInfo(new long[] { dl.getLockOwnerId() }, true, true)[0]).getThreadId() != ti.getThreadId()) {
							info += "\t" + dl.getThreadName() + " is waiting to lock " + dl.getLockInfo().toString() + " which is held by " + dl.getLockOwnerName() + "\n";
						}
					}
					_log.warn(info,Config.SERVER_ID,"������Ϣ");

					if (Config.RESTART_ON_DEADLOCK) {
						Announcements an = Announcements.getInstance();
						an.announceToAll("Server has stability issues - restarting now.");
						Shutdown.getInstance().startTelnetShutdown("DeadLockDetector - Auto Restart", 60, true);
					}

				}
				Thread.sleep(_sleepTime);
			} catch (Exception e) {
				_log.error("DeadLockDetector: error",Config.SERVER_ID, e);
			}
		}
	}
}
